﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

namespace Netra
{
    class Fleet:IPosition
    {
        private static double speed =0.25;

        public string Name { get; set; }

        private Position pos;
        public Position Pos { get { return pos; } }

        public IPosition Aim {get;set;}

        private TradeRoute trade_route;

        private class CInfo
        {
            public int Quantity;

            public CInfo()
            {
                Quantity = 0;
            }
            public CInfo(int quantity)
            {
                Quantity = quantity;
            }
        }

        private List<Ship> ships;
        private Dictionary<Merch, CInfo> merchs;

        public Fleet(IPosition where)
        {
            pos = where.Pos;
            Aim = this;
            ships = new List<Ship>();
            merchs = new Dictionary<Merch, CInfo>();
        }

        public int StorageSpace
        {
            get
            {
                return 10;
            }
        }

        public int StorageUsed
        {
            get
            {
                return merchs.Values.Select(t => t.Quantity).Sum();
            }
        }

        public int StorageAvail
        {
            get
            {
                return StorageSpace - StorageUsed;
            }
        }

        public void AddMerch(Merch ware, int quantity)
        {
            if (StorageAvail >= quantity)
            {
                CInfo wi;
                if (!merchs.TryGetValue(ware, out wi))
                    merchs[ware] = wi = new CInfo(quantity: 0);
                wi.Quantity += quantity;
            }
            else
                throw new System.InvalidOperationException("Fleet cannot get more merchandise than available storage it has");
        }

        public void TakeMerch(Merch ware, int quantity)
        {
            if (!merchs.ContainsKey(ware))
                merchs[ware] = new CInfo(quantity: 0);

            if (merchs[ware].Quantity >= quantity)
            {
                merchs[ware].Quantity -= quantity;
            }
            else
                throw new System.ArgumentException("Fleet does not have so many merchandise", "quantity");
        }

        public Dictionary<Merch, int> GetMerchQuant()
        {
            Dictionary<Merch, int> merch_quant = new Dictionary<Merch, int>();
            foreach (KeyValuePair<Merch, CInfo> elem in merchs)
            {
                merch_quant[elem.Key]=elem.Value.Quantity;
            }
            return merch_quant;
        }

        public float Reputation()
        {
            return 0;
        }

        public void Move()
        {
            if (Moving())
            {
                pos.MoveTowards(Aim.Pos, speed);
                if (pos.Distance(Aim.Pos) < 1e-4)
                {
                    Planet planet=null;
                    if (Aim is Planet)
                    {
                        ((Planet)Aim).Dock(this);
                        planet=(Planet)Aim;
                    }
                    if (trade_route == null)
                    {
                        Aim = this;
                    }
                    else
                    {
                        Dictionary<Merch, int> deals = trade_route.GetCurrentDeals();
                        foreach (KeyValuePair<Merch, int> deal in deals)
                        {
                            if (deal.Value >= 0)
                            {
                                TradeMgmt.Deals.RegisterPurchase(planet, this, deal.Key, deal.Value);
                            }
                            else
                            {
                                TradeMgmt.Deals.RegisterPurchase(planet, this, deal.Key, -deal.Value);
                            }
                        }
                        Aim = trade_route.Next();
                    }
                }
            }
        }

        public bool Moving()
        {
            return Aim != this;
        }

        public override string ToString()
        {
            string s = "Fleet: " + Name +" position: "+pos.ToString()+ "\nTransported merchandises:\n";
            foreach (KeyValuePair<Merch,CInfo> m in merchs)
            {
                s += " "+m.Key.Name + " amount: " + m.Value.Quantity + "\n";
            }
            s += " Storage: used: " + StorageUsed.ToString() + " avail:" + StorageAvail + " total: " + StorageSpace + "\n";
            return s;
        }

        public void AssignTradeRoute(TradeRoute tr)
        {
            trade_route = tr;
            Aim = trade_route.Next();
        }

        public void DeleteTradeRoute()
        {
            trade_route = null;
        }

        public bool IsTradeRouteAssigned()
        {
            return trade_route != null;
        }

        public TradeRoute GetTradeRoute()
        {
            if (IsTradeRouteAssigned())
            {
                return trade_route;
            }
            else
            {
                throw new System.InvalidOperationException("Fleet does not have trade route assigned");
            }
        }
    }
}
